#ifndef DDSMODULAR_H
#define DDSMODULAR_H

#include <QMap>
#include <tuple>
#include <QDebug>

#include "../dds/CSMXPv3.h"
#include "ndds/ndds_cpp.h"
#include "../dds/CSMXPv3Support.h"

#define cout qDebug() << "[" << __FILE__ << ":" << __LINE__ << "]"

/*
 * @file ddsmodular.h
 * @brief RTI DDS 封装
 * @date 2020-8-27
 */

struct DDSMPub {
    DDSTopic* topic;
    CSMXPv3* instance;
    DDSDataWriter* writer;
};

using MQP = QMap<std::string, DDSMPub>;
using TupMsg = std::tuple<ushort, ushort, std::vector<char>>;

using Func = void(*)(const TupMsg&);

// 发布者类
class Publisher {
public:
    Publisher();
    ~Publisher();
    static int shutdown();                       // 关闭发布端，程序自动执行
    static int initPublisher(int);               // 初始化发布端

    /*
     * @brief: 创建话题
     * param[in]: std::string 话题名字
     * param[in]: bool 是否可靠
     * param[in]: bool redundancy 是否冗余、默认值为false
     * param[in]: int priority 冗余优先级、默认值为0，redundancy的值为true时，该值必须被设置为1或2
     */
    void createTopic(const std::string&, bool, bool redundancy = false, const int& priority = 0);
    void publish4Topic(const std::string&, const TupMsg&);  // 发布话题
    void deleteTopic(const std::string&);        // 删除话题

private:
    static MQP m_mqp;                            // 发布端 话题-写者 集合
    static int m_num;                            // 对象数量，为0时调用shutdown
    static DDSPublisher* m_publisher;            // 发布者
    static DDSDomainParticipant* m_participant;  // 发布端句柄

    DDS_ReturnCode_t m_retcode;                  // 返回值存储
    CSMXPv3DataWriter* CSMXPv3_writer;           // 数据写者
};

class CSMXPv3Listener : public DDSDataReaderListener {
  public:
    virtual void on_requested_deadline_missed(
        DDSDataReader* /*reader*/,
        const DDS_RequestedDeadlineMissedStatus& /*status*/) {}

    virtual void on_requested_incompatible_qos(
        DDSDataReader* /*reader*/,
        const DDS_RequestedIncompatibleQosStatus& /*status*/) {}

    virtual void on_sample_rejected(
        DDSDataReader* /*reader*/,
        const DDS_SampleRejectedStatus& /*status*/) {}

    virtual void on_liveliness_changed(
        DDSDataReader* /*reader*/,
        const DDS_LivelinessChangedStatus& /*status*/) {}

    virtual void on_sample_lost(
        DDSDataReader* /*reader*/,
        const DDS_SampleLostStatus& /*status*/) {}

    virtual void on_subscription_matched(
        DDSDataReader* /*reader*/,
        const DDS_SubscriptionMatchedStatus& /*status*/) {}

    virtual void on_data_available(DDSDataReader* reader);

    CSMXPv3Listener(Func fun) : m_fun(fun) {}

private:
    Func m_fun;
};

struct DDSMSub {
    DDSDataReader *reader = nullptr;
    DDSTopic *topic = nullptr;
};

using MQS = QMap<std::string, DDSMSub>;

// 订阅者类
class Subscriber {
public:
    Subscriber();
    ~Subscriber();
    static int shutdown();                       // 关闭订阅端，程序自动执行
    static void initSubcriber();                 // 初始化订阅端，程序自动执行

    /*
     * @brief: 监听话题
     * param[in]: std::string 话题名字
     * param[in]: Func 回调函数，接受到数据后执行的操作
     * param[in]: bool 是否可靠
     * param[in]: bool redundancy 是否冗余，默认值为false
     */
    void listenTopic(const std::string&, Func, bool, bool redundancy = false);
    void cancelTopic(const std::string&);        // 取消指定话题的监听

private:
    static MQS m_mqs;                            // 订阅端 话题-读者 集合
    static int m_num;                            // 对象数量，为0时调用shutdown
    static DDSSubscriber *m_subscriber;          // 订阅者
    static DDSDomainParticipant* m_participant;  // 订阅端句柄

    DDS_ReturnCode_t m_retcode;                  // 返回值存储
};

#endif // DDSMODULAR_H
